#ifndef _UIO_H_
#define _UIO_H_

#include <iostream>
#include <thread>
#include <fcntl.h>   //define O_WRONLY and O_RDONLY 
#include <sys/ioctl.h>
#include <sys/types.h>
#include <semaphore.h>
#include <poll.h>                 //添加poll头文件
#include <queue>
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <stdint.h>

#include "dataShare.h"

using namespace std;

#define DATA_NORMAL_HANDER  0xaa55
#define DATA_EXTERNEL_HANDER   0xBB66
#define DATA_EXTERNEL_TAIL  0xBB67


#define CALIB_FILES     8
//IRQ0
#define INTC_JESD204                    "/dev/uio0"
#define INTC_H_MANUALSEND               "/dev/uio1"
#define INTC_V_MANUALSEND               "/dev/uio2"
#define INTC_AUTO                       "/dev/uio3"
#define INTC_H_MANUALRECVICE            "/dev/uio4"
#define INTC_V_MANUALRECVICE            "/dev/uio5"
#define INTC_IQ0_TWOBUF                 "/dev/uio6"            //观测通道乒乓区0满中断
#define INTC_IQ1_TWOBUF                 "/dev/uio7"           //观测通道乒乓区1满中断

#define INTC_FILES      8
//IRQ1
#define INTC_DMA_ERR                    "/dev/uio8"         //时序卡DMA错误中断
#define INTC_CALI_DMA_ERR               "/dev/uio9"         //校准数据传输DMA错误中断
#define INTC_AD_OBSDMA                  "/dev/uio10"        //AD组件原始数据观测DMA中断
#define INTC_DBF_OBSDMA                 "/dev/uio11"        //DBF原始数据观测DMA中断
#define INTC_AXI_IRQ                    "/dev/uio12"        //AXI中断控制器中断
#define INTC_AXI_GPIO                   "/dev/uio13"        //锁定检测GPIO中断
#define INTC_AXI_GPS                    "/dev/uio14"        //gps 串口中断
#define INTC_AXI_SERVO                  "/dev/uio15"        //伺服 串口中断

#define AXIINTC_FILES   5
//AXI_INTC
#define AXIINTC_DAC_DMA                 "/dev/uio16"        //AXI DAC DMA中断
#define AXIINTC_DAC_0                   "/dev/uio17"        //DAC 中断0
#define AXIINTC_DAC_1                   "/dev/uio18"        //DAC 中断1
#define AXIINTC_DMA_TWOBUF              "/dev/uio19"        //观测通道DMA中断
#define AXIINTC_CDMA_0                  "/dev/uio20"        //CDMA中断

#pragma pack(push, 1)

// Byte7	Byte6	Byte5	Byte4	Byte3	Byte2	Byte1	Byte0
// 极化模式		PRT计数		波位号		外部触发计数	
// 发射子频点0虚部				发射子频点0实部部			
// 发射子频点1虚部				"发射子频点1实部部
// "			
// DBF波束0虚部				DBF波束0实部			
// DBF波束1虚部				DBF波束1实部			
// DBF波束2虚部				DBF波束2实部			
// DBF波束3虚部				DBF波束3实部			
// DBF波束4虚部				DBF波束4实部			
// DBF波束5虚部				DBF波束5实部			
// DBF波束6虚部				DBF波束6实部			
// DBF波束7虚部				DBF波束7实部			
// DBF波束8虚部				DBF波束8实部			
// DBF波束9虚部				DBF波束9实部			
// DBF波束10虚部				DBF波束10实部			
// DBF波束11虚部				DBF波束11实部			
// DBF波束12虚部				DBF波束12实部			
// DBF波束13虚部				DBF波束13实部			
// DBF波束14虚部				DBF波束14实部			
// DBF波束15虚部				DBF波束15实部			

struct darktsFrame
{
    //外部触发计数
    uint16_t m_externelCnt;
    //本帧波位号
    uint16_t m_beamCode;
    //PRT计数
    uint16_t m_prtCnt;
    //极化信息2023-7-12
    uint16_t m_polar;
    //IQ数据
    uint32_t m_sendIQ[2][2]; 
    uint32_t m_recviceIQ[16][2];
};

struct darktsAmpPhaseFrame
{
    //帧头
    uint16_t m_externelCnt;
    //本帧波位号
    uint16_t m_beamCode;
    //PRT计数
    uint16_t m_prtCnt;
    //极化信息2023-7-12
    uint16_t m_polar;
    //IQ数据
    float m_sendAmpPhase[2][2];
    float m_recAmpPhase[16][2]; 
};


#define SINGLE_POINT_DARKTS_PRT 4096          //每个波位最大支持512个prt*每个prt最大支持16个波束
#define MAX_DARKTS_SIMPALE 200  //最大触发点 = 200个点
//当前采样点有效prt个数=prtNum[0]+...+prtNum[31];

//每个采样点集合4M大小
struct oneSimple_prt_stc
{
    uint8_t beamNum;//当前采样点的有效波位个数
    uint8_t prtNum[32];//当前采样点的每个波位的有效prt个数
    uint8_t prtPolarInfo[SINGLE_POINT_DARKTS_PRT]; //用于记录每个pr的极化信息
    float hamp[32][SINGLE_POINT_DARKTS_PRT];
    float hphase[32][SINGLE_POINT_DARKTS_PRT];
    float vamp[32][SINGLE_POINT_DARKTS_PRT];
    float vphase[32][SINGLE_POINT_DARKTS_PRT];
};



struct txObsFrame
{
    //帧头
    uint16_t frame_header;
    //CPI计算
    uint16_t cpi_cnt;
    //波形码
    uint16_t wave_code;
    //方位码
    uint16_t local_code;
    //本帧波位号
    uint16_t beam_code;
    //总采样点数
    uint16_t tatol_simple;
    //外部触发计数
    uint16_t externel_cnt;
    //PRT计数
    uint16_t prt_cnt;
    //俯仰触发扫描完成计数
    uint16_t scan_cnt;
    //秒
    uint16_t sec;
    //分
    uint16_t min;
    //时
    uint16_t hour;
    //子频点0/1/2/3采样点数
    uint16_t simple_num[4];
    //IQ数据
    uint64_t m_iqBuffer[4094][2];
};

struct txObsUpdate
{
    //帧头
    uint16_t frame_header;
    //CPI计算
    uint16_t cpi_cnt;
    //波形码
    uint16_t wave_code;
    //方位码
    uint16_t local_code;
    //本帧波位号
    uint16_t beam_code;
    //总采样点数
    uint16_t tatol_simple;
    //外部触发计数
    uint16_t externel_cnt;
    //PRT计数
    uint16_t prt_cnt;
    //俯仰触发扫描完成计数
    uint16_t scan_cnt;
    //秒
    uint16_t sec;
    //分
    uint16_t min;
    //时
    uint16_t hour;
    //子频点0/1/2/3采样点数
    uint16_t simple_num[4];
    //IQ数据
    uint64_t m_iqBuffer[2048];
};


//发射校准数据结构
struct txCalibrationFrame
{
    //采样点数
    uint16_t m_simpleNum;
    //校准参数PRT数
    uint16_t m_prtNum;
    //校准参数CPI数
    uint16_t m_cpiNum;
    //not_use
    uint16_t m_notUse;
    //IQ数据
    uint64_t m_iqBuffer[4095];
};





/*
根据采样点提取出DBF观测数据读所有HV极化接收观测数据，直接上报给上位机处理
实部称为 I (n-phase)分量，将虚部称为 Q(uadrature)分量
频点0信号宽度		采样点数		    PRT计数		波形码	
				                    波位号		频点1信号宽度	
采样点0H极化接收波束0虚部				采样点0H极化接收波束0实部			
采样点0V极化接收波束0虚部				采样点0V极化接收波束0实部			
采样点0H极化接收波束1虚部				采样点0H极化接收波束1实部			
采样点0V极化接收波束1虚部				采样点0V极化接收波束1实部			
...	...	...	...	...	...	...	...
采样点0H极化接收波束15虚部				采样点0H极化接收波束15实部			
采样点0V极化接收波束15虚部				采样点0V极化接收波束15实部			
*/
//这个结构体为一个采样点的数据结构起始地址=0X503200000 （DBF 原始数据采样触发）
struct rxDbfObsFrame
{
    //波形码
    uint16_t m_waveCode;
    //PRT计数
    uint16_t m_prtNum;
    //采样点
    uint16_t m_simple;
    //频点0信号宽度
    uint16_t m_freq0Wave;
    //频点1信号宽度
    uint16_t m_freq1Wave;
    //波位号
    uint16_t m_beamNum;
    //预留
    uint32_t m_notUser;
    //一个采样点的数据，总共16组波束，每组波束包含一个H，一个V的IQ数据
    uint64_t m_iqBuffer[4095][32];
};

//接收校准数据结构,为单次触发一次数据 0X02400000
/*
BYTE7	BYTE6	BYTE5	BYTE4	BYTE3	BYTE2	BYTE1	BYTE0
波形码		采样点		PRT计数		波位号	
BYTE7	BYTE6	BYTE5	BYTE4	BYTE3	BYTE2	BYTE1	BYTE0
通道0采样点0虚部				通道0采样点0实部			
BYTE7	BYTE6	BYTE5	BYTE4	BYTE3	BYTE2	BYTE1	BYTE0
通道1采样点0虚部				通道1采样点0实部			
BYTE7	BYTE6	BYTE5	BYTE4	BYTE3	BYTE2	BYTE1	BYTE0
通道2采样点0虚部				通道2采样点0实部			
....	....	....	....	....	....	....	....
BYTE7	BYTE6	BYTE5	BYTE4	BYTE3	BYTE2	BYTE1	BYTE0
通道29采样点0虚部				通道29采样点0实部			
BYTE7	BYTE6	BYTE5	BYTE4	BYTE3	BYTE2	BYTE1	BYTE0
通道30采样点0虚部				通道30采样点0实部			
BYTE7	BYTE6	BYTE5	BYTE4	BYTE3	BYTE2	BYTE1	BYTE0
通道31采样点0虚部				通道31采样点0实部		
*/	
struct rxCalibrationFrame
{
    //波位号
    uint16_t m_beamNum;
    //PRT计数
    uint16_t m_prtNum;
    //采样点
    uint16_t m_simple;
    //波形码
    uint16_t m_waveCode;
    //代表了32个通道的采样点0的IQ数据
    uint64_t m_iqBuffer[4095][32];
};

struct adcObsFrame
{
    int16_t m_adcSrc[32768][4];
};

struct dbfObsWork
{
    uint8_t m_polar;
    uint8_t m_channel;
    uint16_t m_simple;
};

struct rxObsWork
{
    uint8_t m_freqPoint;
    uint8_t m_polar;
    uint8_t m_channel;
    uint16_t m_simple;
};

struct txObsWork
{
    bool update;            //上报标志位，自清0
    int m_runCount;         //运行次数0-127
    uint8_t m_channel;      //指定观测通道
    uint8_t m_beamCode;     //指定波位号0-31
    uint8_t m_freqPoint;    //指定频点0-1
};

/*** 
 * @description: 对应AD OB Mem Struct 0X0340_0000 PLDDR
 * @return {*}
 */
struct adcObsWork
{
    uint8_t m_channel;
    uint16_t m_simple;
};

#pragma pack(pop)



#define TX_CALIB_CHN_OFFSET     0x8000  //32K
#define TX_CALIB_OFFSET         0x100000
#define TX_OBS_OFFSET           0x10000
#define TX_OBS_CHN_OFFSET       0x800000

#define RX_CALIB_CHN_OFFSET     0x400
#define RX_CALIB_OFFSET         0x400000

#define PS_IQA0_OFFSET 0x510000000    //A通道
#define PS_IQA1_OFFSET 0x510800000    //A通道
#define PS_IQB0_OFFSET 0x511000000    //B通道
#define PS_IQB1_OFFSET 0x511800000    //B通道
#define PS_IQC0_OFFSET 0x512000000    //C通道
#define PS_IQC1_OFFSET 0x512800000    //C通道
#define PS_IQD0_OFFSET 0X513000000    //D通道
#define PS_IQD1_OFFSET 0x513800000    //D通道

#define DARK_SIZE_ROOM          44
#define DARK_OFFSET	            0x100
#define DARK_HALF               0x1000 //暗室一半数据大小
#define DARK_CAP 	            0x2000 //暗室总数据大小


typedef enum
{   uio_top,uio_bottom,uio_no  }darkHandleMode;


class transmit : public sharePub
{
public:
    transmit() { m_status = uio_noReply; };
    ~transmit() {};
    void request(int m) override;
    void pulish(int m,vector<uint8_t>& dataIn) override;
};

class Uio
{
public:
    Uio();
    ~Uio();    
private:
    
    std::thread * irq0Fd;                   /* 中断线程 */
    std::thread * irq1Fd;                   /* 中断线程 */
    thread * workFd;                        /*波形触发工作线程*/
    thread * topWorkFd;                     /*暗室上半工作线程*/
    thread * bottomWorkFd;                  /*暗室下半工作线程*/
    thread * packagedFd;                    /*打包上报线程*/
    thread * obsTxFd;                       /* 用于持续观测校准通道的线程 */
    static void irq0Handle(Uio *argc);
    static void irq1Handle(Uio *argc);
    static void topHalfWork(Uio *argc);
    static void bottomHalfWork(Uio *argc);
    static void work(Uio *argc);
    static void packageTask(Uio *argc);
    static void txObsWork(Uio *argc);       /* 用于持续观测校准通道的线程 */

    void darktsHandle(darkHandleMode m);
    void processDarktsData(int darkts_mode, const darktsFrame& package, struct oneSimple_prt_stc& oneSimpe,int m_debug);
    void processDarktsSendData(const darktsFrame& package,const darktsAmpPhaseFrame& m_data,struct oneSimple_prt_stc& oneSimpe);
    void processDarktsRecvData(const darktsFrame& package,const darktsAmpPhaseFrame& m_data,struct oneSimple_prt_stc& oneSimpe);

    void recvSendCalibreation(uioMode m);   /* 用于处理校准数据上报 */
public:
    class transmit *m_pub;
    struct dbfObsWork m_dbfWork;
    struct rxObsWork m_rxWork;
    struct txObsWork m_txWork;
    struct adcObsWork m_adcWork;
    uioMode m_workStatus;
public:
    float m_amp[32],m_phase[32];
    bool m_isRunning;/* 协议解析线程运行标志*/
    void *m_darktsAddr, *m_IqAddrA, *m_IqAddrB, *m_IqAddrC, *m_IqAddrD;
    int m_memFile = -1;
    int calibFd[CALIB_FILES];//自动校准文件集
    int intcFd[INTC_FILES];
    int axiFd[AXIINTC_FILES];
    bool isPackage = false; //用于打包上报读标志

    struct oneSimple_prt_stc darktsPrtSend[MAX_DARKTS_SIMPALE]; //总共200个触发点
#define DARK_QUEUE_MAX  32*64*2*200 //32个波位每个波位64个prt×2个极化×200个触发点
    sem_t g_packageTask;
    sem_t g_obsSem;
    sem_t g_dbfSem;

    bool u_DarktsComplete = false;//暗室数据完整标志位
    
public:
    bool Init();
    int openUio(const char* filename);
    void Sendto(uioMode m);
    int handleFrame(const struct darktsFrame& src,struct darktsAmpPhaseFrame& dst);
    
    void dataPackage(int m);
    bool repairDarkts();
    void obsRxHandle();
    void obsTxHandle();
    void obsDbfHandle();
    void obsAdcHandle();
    void tiggerObsSem(uioMode m);
    int sysRevDarktsBeamPoint(int i);
};
//用于上报TCP暗室的数组200K
extern vector<uint8_t> DarktsUpdateVct;

#endif